/*
  Morse code

  Transmits morse messages read from serial port.
  
  Created on 27 december 2013
  By Marco and Stefano Ricci <stefano@ricciandco.it>
*/
#include <Esplora.h>

typedef struct {
  byte ascii;
  byte morse;
} morse_t;

/*
 * the morse "code" is built by converting each point (ti) to 0 and each line (ta) to 1, reversing and then prepending a 1 as most significative bit
 * 'A' = . - --> 01 --> 10 --> 110 --> 6
 * 'B' = - . . . --> 1000 --> 0001 --> 10001 --> 17
 * 'C' = - . - . --> 1010 --> 0101 --> 10101 --> 21
 * etc.
 */
morse_t morse[] = {
  {'A', 6},
  {'B', 17},
  {'C', 21},
  {'D', 9},
  {'E', 2},
  {'F', 20},
  {'G', 11},
  {'H', 16},
  {'I', 4},
  {'J', 30},
  {'K', 13},
  {'L', 18},
  {'M', 7},
  {'N', 5},
  {'O', 15},
  {'P', 22},
  {'Q', 27},
  {'R', 10},
  {'S', 8},
  {'T', 3},
  {'U', 12},
  {'V', 24},
  {'W', 14},
  {'X', 25},
  {'Y', 29},
  {'Z', 19},
  {'0', 63},
  {'1', 62},
  {'2', 60},
  {'3', 56},
  {'4', 48},
  {'5', 32},
  {'6', 33},
  {'7', 35},
  {'8', 39},
  {'9', 47},
  {'.', 106},
  {',', 115},
  {'?', 76},
  {'\'', 94},
  {'!', 117},
  {'/', 41},
  {'(', 45},
  {')', 109},
  {'&', 34},
  {':', 71},
  {';', 85},
  {'=', 49},
  {'+', 42},
  {'-', 97},
  {'_', 108},
  {'"', 82},
  {'$', 200},
  {'@', 86},
  {'\0', 0}
};

int POINTLEN = 50;
int BRIGHTNESS = 10;
int FREQ = 440;


void setup() {
  // initialize the serial communication:
  Serial.begin(9600);
}

void loop() {
  byte incomingByte;
  if (Serial.available() > 0) {
    incomingByte = Serial.read();
    
    sendMorseCode(incomingByte);
    delay(3*POINTLEN);
  }
}

void sendMorseCode(byte b) { 
  
  byte morseCode = 0;
  
  if (b == ' ') {
    delay(7*POINTLEN);
    return;
  }
  
  if (isalpha(b)) {
    b = toupper(b);
  }
  for (int i=0; morse[i].ascii != '\0'; i++) {
    if (morse[i].ascii == b) {
      morseCode = morse[i].morse;
      break;
    }
  }
  
  if (morseCode == 0) {
    // invalid char
    Serial.print("invalid char: ");
    Serial.println(b);
    return;
  }
  
  Serial.print((char)b); Serial.print(": ");
  while (morseCode > 1) { // do not consider the most significative bit!
    byte impulse = morseCode % 2;
    if (impulse == 0) {
      // send 'point'
      Serial.print(".");
      sendPulse(BRIGHTNESS, POINTLEN);
    } else {
      // send line
      Serial.print("-");
      sendPulse(BRIGHTNESS, 3*POINTLEN);
    }
    // delay between pulse
    delay(POINTLEN);
    morseCode /= 2;
  }
  Serial.println("");

}

void sendPulse(byte brightness, unsigned int duration) {
  // switch led on
  Esplora.writeRGB(brightness,brightness,brightness);
  Esplora.tone(FREQ);
  delay(duration);
  // switch led off
  Esplora.writeRGB(0,0,0);
  Esplora.noTone();
}

